/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package controladores;

import controladores.exceptions.IllegalOrphanException;
import controladores.exceptions.NonexistentEntityException;
import controladores.exceptions.PreexistingEntityException;
import entidades.Reserva;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entidades.Reservarecurso;
import entidades.Reservahotel;
import java.util.ArrayList;
import java.util.List;
import entidades.Reservarestaurante;
import entidades.Reservatransporte;

/**
 *
 * @author Andres
 */
public class ReservaJpaController {

    public ReservaJpaController() {
        emf = Persistence.createEntityManagerFactory("proyectoCongresoPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Reserva reserva) throws PreexistingEntityException, Exception {
        if (reserva.getReservahotelList() == null) {
            reserva.setReservahotelList(new ArrayList<Reservahotel>());
        }
        if (reserva.getReservarestauranteList() == null) {
            reserva.setReservarestauranteList(new ArrayList<Reservarestaurante>());
        }
        if (reserva.getReservatransporteList() == null) {
            reserva.setReservatransporteList(new ArrayList<Reservatransporte>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Reservarecurso reservarecurso = reserva.getReservarecurso();
            if (reservarecurso != null) {
                reservarecurso = em.getReference(reservarecurso.getClass(), reservarecurso.getReservaCodigoreserva());
                reserva.setReservarecurso(reservarecurso);
            }
            List<Reservahotel> attachedReservahotelList = new ArrayList<Reservahotel>();
            for (Reservahotel reservahotelListReservahotelToAttach : reserva.getReservahotelList()) {
                reservahotelListReservahotelToAttach = em.getReference(reservahotelListReservahotelToAttach.getClass(), reservahotelListReservahotelToAttach.getReservahotelPK());
                attachedReservahotelList.add(reservahotelListReservahotelToAttach);
            }
            reserva.setReservahotelList(attachedReservahotelList);
            List<Reservarestaurante> attachedReservarestauranteList = new ArrayList<Reservarestaurante>();
            for (Reservarestaurante reservarestauranteListReservarestauranteToAttach : reserva.getReservarestauranteList()) {
                reservarestauranteListReservarestauranteToAttach = em.getReference(reservarestauranteListReservarestauranteToAttach.getClass(), reservarestauranteListReservarestauranteToAttach.getReservarestaurantePK());
                attachedReservarestauranteList.add(reservarestauranteListReservarestauranteToAttach);
            }
            reserva.setReservarestauranteList(attachedReservarestauranteList);
            List<Reservatransporte> attachedReservatransporteList = new ArrayList<Reservatransporte>();
            for (Reservatransporte reservatransporteListReservatransporteToAttach : reserva.getReservatransporteList()) {
                reservatransporteListReservatransporteToAttach = em.getReference(reservatransporteListReservatransporteToAttach.getClass(), reservatransporteListReservatransporteToAttach.getReservatransportePK());
                attachedReservatransporteList.add(reservatransporteListReservatransporteToAttach);
            }
            reserva.setReservatransporteList(attachedReservatransporteList);
            em.persist(reserva);
            if (reservarecurso != null) {
                Reserva oldReservaOfReservarecurso = reservarecurso.getReserva();
                if (oldReservaOfReservarecurso != null) {
                    oldReservaOfReservarecurso.setReservarecurso(null);
                    oldReservaOfReservarecurso = em.merge(oldReservaOfReservarecurso);
                }
                reservarecurso.setReserva(reserva);
                reservarecurso = em.merge(reservarecurso);
            }
            for (Reservahotel reservahotelListReservahotel : reserva.getReservahotelList()) {
                Reserva oldReservaOfReservahotelListReservahotel = reservahotelListReservahotel.getReserva();
                reservahotelListReservahotel.setReserva(reserva);
                reservahotelListReservahotel = em.merge(reservahotelListReservahotel);
                if (oldReservaOfReservahotelListReservahotel != null) {
                    oldReservaOfReservahotelListReservahotel.getReservahotelList().remove(reservahotelListReservahotel);
                    oldReservaOfReservahotelListReservahotel = em.merge(oldReservaOfReservahotelListReservahotel);
                }
            }
            for (Reservarestaurante reservarestauranteListReservarestaurante : reserva.getReservarestauranteList()) {
                Reserva oldReservaOfReservarestauranteListReservarestaurante = reservarestauranteListReservarestaurante.getReserva();
                reservarestauranteListReservarestaurante.setReserva(reserva);
                reservarestauranteListReservarestaurante = em.merge(reservarestauranteListReservarestaurante);
                if (oldReservaOfReservarestauranteListReservarestaurante != null) {
                    oldReservaOfReservarestauranteListReservarestaurante.getReservarestauranteList().remove(reservarestauranteListReservarestaurante);
                    oldReservaOfReservarestauranteListReservarestaurante = em.merge(oldReservaOfReservarestauranteListReservarestaurante);
                }
            }
            for (Reservatransporte reservatransporteListReservatransporte : reserva.getReservatransporteList()) {
                Reserva oldReservaOfReservatransporteListReservatransporte = reservatransporteListReservatransporte.getReserva();
                reservatransporteListReservatransporte.setReserva(reserva);
                reservatransporteListReservatransporte = em.merge(reservatransporteListReservatransporte);
                if (oldReservaOfReservatransporteListReservatransporte != null) {
                    oldReservaOfReservatransporteListReservatransporte.getReservatransporteList().remove(reservatransporteListReservatransporte);
                    oldReservaOfReservatransporteListReservatransporte = em.merge(oldReservaOfReservatransporteListReservatransporte);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findReserva(reserva.getCodigoreserva()) != null) {
                throw new PreexistingEntityException("Reserva " + reserva + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Reserva reserva) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Reserva persistentReserva = em.find(Reserva.class, reserva.getCodigoreserva());
            Reservarecurso reservarecursoOld = persistentReserva.getReservarecurso();
            Reservarecurso reservarecursoNew = reserva.getReservarecurso();
            List<Reservahotel> reservahotelListOld = persistentReserva.getReservahotelList();
            List<Reservahotel> reservahotelListNew = reserva.getReservahotelList();
            List<Reservarestaurante> reservarestauranteListOld = persistentReserva.getReservarestauranteList();
            List<Reservarestaurante> reservarestauranteListNew = reserva.getReservarestauranteList();
            List<Reservatransporte> reservatransporteListOld = persistentReserva.getReservatransporteList();
            List<Reservatransporte> reservatransporteListNew = reserva.getReservatransporteList();
            List<String> illegalOrphanMessages = null;
            if (reservarecursoOld != null && !reservarecursoOld.equals(reservarecursoNew)) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("You must retain Reservarecurso " + reservarecursoOld + " since its reserva field is not nullable.");
            }
            for (Reservahotel reservahotelListOldReservahotel : reservahotelListOld) {
                if (!reservahotelListNew.contains(reservahotelListOldReservahotel)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Reservahotel " + reservahotelListOldReservahotel + " since its reserva field is not nullable.");
                }
            }
            for (Reservarestaurante reservarestauranteListOldReservarestaurante : reservarestauranteListOld) {
                if (!reservarestauranteListNew.contains(reservarestauranteListOldReservarestaurante)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Reservarestaurante " + reservarestauranteListOldReservarestaurante + " since its reserva field is not nullable.");
                }
            }
            for (Reservatransporte reservatransporteListOldReservatransporte : reservatransporteListOld) {
                if (!reservatransporteListNew.contains(reservatransporteListOldReservatransporte)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Reservatransporte " + reservatransporteListOldReservatransporte + " since its reserva field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (reservarecursoNew != null) {
                reservarecursoNew = em.getReference(reservarecursoNew.getClass(), reservarecursoNew.getReservaCodigoreserva());
                reserva.setReservarecurso(reservarecursoNew);
            }
            List<Reservahotel> attachedReservahotelListNew = new ArrayList<Reservahotel>();
            for (Reservahotel reservahotelListNewReservahotelToAttach : reservahotelListNew) {
                reservahotelListNewReservahotelToAttach = em.getReference(reservahotelListNewReservahotelToAttach.getClass(), reservahotelListNewReservahotelToAttach.getReservahotelPK());
                attachedReservahotelListNew.add(reservahotelListNewReservahotelToAttach);
            }
            reservahotelListNew = attachedReservahotelListNew;
            reserva.setReservahotelList(reservahotelListNew);
            List<Reservarestaurante> attachedReservarestauranteListNew = new ArrayList<Reservarestaurante>();
            for (Reservarestaurante reservarestauranteListNewReservarestauranteToAttach : reservarestauranteListNew) {
                reservarestauranteListNewReservarestauranteToAttach = em.getReference(reservarestauranteListNewReservarestauranteToAttach.getClass(), reservarestauranteListNewReservarestauranteToAttach.getReservarestaurantePK());
                attachedReservarestauranteListNew.add(reservarestauranteListNewReservarestauranteToAttach);
            }
            reservarestauranteListNew = attachedReservarestauranteListNew;
            reserva.setReservarestauranteList(reservarestauranteListNew);
            List<Reservatransporte> attachedReservatransporteListNew = new ArrayList<Reservatransporte>();
            for (Reservatransporte reservatransporteListNewReservatransporteToAttach : reservatransporteListNew) {
                reservatransporteListNewReservatransporteToAttach = em.getReference(reservatransporteListNewReservatransporteToAttach.getClass(), reservatransporteListNewReservatransporteToAttach.getReservatransportePK());
                attachedReservatransporteListNew.add(reservatransporteListNewReservatransporteToAttach);
            }
            reservatransporteListNew = attachedReservatransporteListNew;
            reserva.setReservatransporteList(reservatransporteListNew);
            reserva = em.merge(reserva);
            if (reservarecursoNew != null && !reservarecursoNew.equals(reservarecursoOld)) {
                Reserva oldReservaOfReservarecurso = reservarecursoNew.getReserva();
                if (oldReservaOfReservarecurso != null) {
                    oldReservaOfReservarecurso.setReservarecurso(null);
                    oldReservaOfReservarecurso = em.merge(oldReservaOfReservarecurso);
                }
                reservarecursoNew.setReserva(reserva);
                reservarecursoNew = em.merge(reservarecursoNew);
            }
            for (Reservahotel reservahotelListNewReservahotel : reservahotelListNew) {
                if (!reservahotelListOld.contains(reservahotelListNewReservahotel)) {
                    Reserva oldReservaOfReservahotelListNewReservahotel = reservahotelListNewReservahotel.getReserva();
                    reservahotelListNewReservahotel.setReserva(reserva);
                    reservahotelListNewReservahotel = em.merge(reservahotelListNewReservahotel);
                    if (oldReservaOfReservahotelListNewReservahotel != null && !oldReservaOfReservahotelListNewReservahotel.equals(reserva)) {
                        oldReservaOfReservahotelListNewReservahotel.getReservahotelList().remove(reservahotelListNewReservahotel);
                        oldReservaOfReservahotelListNewReservahotel = em.merge(oldReservaOfReservahotelListNewReservahotel);
                    }
                }
            }
            for (Reservarestaurante reservarestauranteListNewReservarestaurante : reservarestauranteListNew) {
                if (!reservarestauranteListOld.contains(reservarestauranteListNewReservarestaurante)) {
                    Reserva oldReservaOfReservarestauranteListNewReservarestaurante = reservarestauranteListNewReservarestaurante.getReserva();
                    reservarestauranteListNewReservarestaurante.setReserva(reserva);
                    reservarestauranteListNewReservarestaurante = em.merge(reservarestauranteListNewReservarestaurante);
                    if (oldReservaOfReservarestauranteListNewReservarestaurante != null && !oldReservaOfReservarestauranteListNewReservarestaurante.equals(reserva)) {
                        oldReservaOfReservarestauranteListNewReservarestaurante.getReservarestauranteList().remove(reservarestauranteListNewReservarestaurante);
                        oldReservaOfReservarestauranteListNewReservarestaurante = em.merge(oldReservaOfReservarestauranteListNewReservarestaurante);
                    }
                }
            }
            for (Reservatransporte reservatransporteListNewReservatransporte : reservatransporteListNew) {
                if (!reservatransporteListOld.contains(reservatransporteListNewReservatransporte)) {
                    Reserva oldReservaOfReservatransporteListNewReservatransporte = reservatransporteListNewReservatransporte.getReserva();
                    reservatransporteListNewReservatransporte.setReserva(reserva);
                    reservatransporteListNewReservatransporte = em.merge(reservatransporteListNewReservatransporte);
                    if (oldReservaOfReservatransporteListNewReservatransporte != null && !oldReservaOfReservatransporteListNewReservatransporte.equals(reserva)) {
                        oldReservaOfReservatransporteListNewReservatransporte.getReservatransporteList().remove(reservatransporteListNewReservatransporte);
                        oldReservaOfReservatransporteListNewReservatransporte = em.merge(oldReservaOfReservatransporteListNewReservatransporte);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = reserva.getCodigoreserva();
                if (findReserva(id) == null) {
                    throw new NonexistentEntityException("The reserva with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Reserva reserva;
            try {
                reserva = em.getReference(Reserva.class, id);
                reserva.getCodigoreserva();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The reserva with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Reservarecurso reservarecursoOrphanCheck = reserva.getReservarecurso();
            if (reservarecursoOrphanCheck != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Reserva (" + reserva + ") cannot be destroyed since the Reservarecurso " + reservarecursoOrphanCheck + " in its reservarecurso field has a non-nullable reserva field.");
            }
            List<Reservahotel> reservahotelListOrphanCheck = reserva.getReservahotelList();
            for (Reservahotel reservahotelListOrphanCheckReservahotel : reservahotelListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Reserva (" + reserva + ") cannot be destroyed since the Reservahotel " + reservahotelListOrphanCheckReservahotel + " in its reservahotelList field has a non-nullable reserva field.");
            }
            List<Reservarestaurante> reservarestauranteListOrphanCheck = reserva.getReservarestauranteList();
            for (Reservarestaurante reservarestauranteListOrphanCheckReservarestaurante : reservarestauranteListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Reserva (" + reserva + ") cannot be destroyed since the Reservarestaurante " + reservarestauranteListOrphanCheckReservarestaurante + " in its reservarestauranteList field has a non-nullable reserva field.");
            }
            List<Reservatransporte> reservatransporteListOrphanCheck = reserva.getReservatransporteList();
            for (Reservatransporte reservatransporteListOrphanCheckReservatransporte : reservatransporteListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Reserva (" + reserva + ") cannot be destroyed since the Reservatransporte " + reservatransporteListOrphanCheckReservatransporte + " in its reservatransporteList field has a non-nullable reserva field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            em.remove(reserva);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Reserva> findReservaEntities() {
        return findReservaEntities(true, -1, -1);
    }

    public List<Reserva> findReservaEntities(int maxResults, int firstResult) {
        return findReservaEntities(false, maxResults, firstResult);
    }

    private List<Reserva> findReservaEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Reserva.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Reserva findReserva(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Reserva.class, id);
        } finally {
            em.close();
        }
    }

    public int getReservaCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Reserva> rt = cq.from(Reserva.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
